UNION-based SQLi: fingerprinting de versión en MySQL/Microsoft con version()
Fingerprinting del motor de base de datos en MySQL y Microsoft SQL Server mediante UNION-based SQLi en el filtro de categoría, usando la función version().
1. Target Overview & Vulnerability Summary
El filtro de categoría es inyectable con resultados reflejados en la respuesta (ataque UNION-based). El objetivo del lab es simplemente exponer el string de versión del motor. La función version() es válida en MySQL y Microsoft SQL Server (vía @@version en MSSQL), por lo que el mismo payload sirve para el fingerprint del motor.
| Severidad | Endpoint vulnerable | Root cause |
|---|---|---|
| Medium | GET /filter?category=... |
Concatenación de category en la cláusula WHERE; resultados reflejados en la respuesta |
2. Technical Breakdown & Exploitation Flow
- Determinar la aridad de la query original con
UNION SELECT NULL[, NULL...]hasta que no se produzca error (2 columnas en este lab). - Sustituir la columna compatible con texto por la función de versión:
' UNION SELECT NULL,version()-- -
GET /filter?category=' UNION SELECT NULL,version()-- - HTTP/1.1
Host: 0a...web-security-academy.net
La respuesta refleja el string del motor, que identifica MySQL o MSSQL (para MSSQL alternativamente @@version). Con la versión expuesta el lab queda resuelto.
3. Root Cause Analysis
La query del filtro se interpola sin prepared statements:
SELECT column1, column2 FROM products WHERE category = 'Gifts'
El branch UNION SELECT permite invocar funciones del motor en columnas compatibles; version() se ejecuta con los privilegios del rol de la app y su salida se serializa en el HTML. Este lab demuestra el primer paso de cualquier escalada UNION-based: fingerprint del motor para elegir el dialecto (funciones de metadatos, concatenación, etc.) del exploit posterior.
4. Secure Remediation
Parametrización de la query:
String sql = "SELECT column1, column2 FROM products WHERE category = ?";
PreparedStatement stmt = connection.prepareStatement(sql);
stmt.setString(1, category);
Defensa en profundidad: rol de BD con menor privilegio que no exponga la versión (por ejemplo, sin SELECT sobre vistas de metadatos) y redacción del string de versión en respuestas públicas si no es necesario.